#include <algorithm>
#include "graphical_commands.h"
#include "media/igraphic.h"
#include "core/value.h"
#include "core/inspector.h"

using namespace Commands;
using namespace Commands::Core;
//-----------------------------------------------------------------------------
Hide::Hide()
: Command<IGraphicElement>(0l)
{}
//-----------------------------------------------------------------------------
float Hide::Execute(const float)
{
    if(IGraphicElement* graphel = GetObject())
    {
        graphel->Hide();
    }
    return 0.0;
}
//-----------------------------------------------------------------------------
bool Hide::IsFinished(void) const
{
    return true;
}
//-----------------------------------------------------------------------------
Hide::~Hide()
{}
//-----------------------------------------------------------------------------
Hide* Hide::Copy(void) const
{
    return new Hide();
}
//-----------------------------------------------------------------------------
void Hide::Accept(Core::Inspector& inspector)
{
    inspector.Inspect(*this);
}
//-----------------------------------------------------------------------------
ShowEndless::ShowEndless()
: Command<IGraphicElement>(0l)
{}
//-----------------------------------------------------------------------------
float ShowEndless::Execute(const float)
{
    if(IGraphicElement* graphel = GetObject())
    {
        graphel->Show();
    }
    return 0.0;
}
//-----------------------------------------------------------------------------
bool ShowEndless::IsFinished(void) const
{
    return false;
}
//-----------------------------------------------------------------------------
ShowEndless::~ShowEndless()
{}
//-----------------------------------------------------------------------------
ShowEndless* ShowEndless::Copy(void) const
{
    return new ShowEndless();
}
//-----------------------------------------------------------------------------
void ShowEndless::Accept(Core::Inspector& inspector)
{
    inspector.Inspect(*this);
}
//-----------------------------------------------------------------------------
SetAngle::SetAngle(float angle)
: Command<IGraphicElement>(0l)
, angle(new Value(angle))
{}
//-----------------------------------------------------------------------------
SetAngle::SetAngle(const Value& angle)
: Command<IGraphicElement>(0l)
, angle(angle.Copy())
{}
//-----------------------------------------------------------------------------
float SetAngle::Execute(const float seconds)
{
    const float consumedSeconds = angle->Execute(seconds);
    if(IGraphicElement* graphel = GetObject())
    {
        graphel->SetAngle(angle->GetValue());
    }
    return consumedSeconds;
}
//-----------------------------------------------------------------------------
bool SetAngle::IsFinished(void) const
{
    return angle->IsFinished();
}
//-----------------------------------------------------------------------------
SetAngle::~SetAngle()
{
    delete angle;
}
//-----------------------------------------------------------------------------
SetAngle* SetAngle::Copy(void) const
{
    return new SetAngle(*angle);
}
//-----------------------------------------------------------------------------
void SetAngle::Accept(Core::Inspector& inspector)
{
    inspector.Inspect(*this);
}
//-----------------------------------------------------------------------------
SetAlpha::SetAlpha(float alpha)
: Command<IGraphicElement>(0l)
, alpha(new Value(alpha))
{}
//-----------------------------------------------------------------------------
SetAlpha::SetAlpha(const Value& alpha)
: Command<IGraphicElement>(0l)
, alpha(alpha.Copy())
{}
//-----------------------------------------------------------------------------
float SetAlpha::Execute(const float seconds)
{
    const float consumedSeconds = alpha->Execute(seconds);
    const unsigned int alphaAsInt = alpha->GetValue() > 255.0 ? 255 : alpha->GetValue() < 0.0 ? 0 : int(alpha->GetValue() + 0.5f);
    if(IGraphicElement* graphel = GetObject())
    {
        graphel->SetAlpha(alphaAsInt);
    }
    return consumedSeconds;
}
//-----------------------------------------------------------------------------
bool SetAlpha::IsFinished(void) const
{
    return alpha->IsFinished();
}
//-----------------------------------------------------------------------------
SetAlpha::~SetAlpha()
{
    delete alpha;
}
//-----------------------------------------------------------------------------
SetAlpha* SetAlpha::Copy(void) const
{
    return new SetAlpha(*alpha);
}
//-----------------------------------------------------------------------------
void SetAlpha::Accept(Core::Inspector& inspector)
{
    inspector.Inspect(*this);
}
//-----------------------------------------------------------------------------
SetXCoord::SetXCoord(float coord)
: Command<IGraphicElement>(0l)
, coord(new Value(coord))
{}
//-----------------------------------------------------------------------------
SetXCoord::SetXCoord(const Value& coord)
: Command<IGraphicElement>(0l)
, coord(coord.Copy())
{}
//-----------------------------------------------------------------------------
float SetXCoord::Execute(const float seconds)
{
    const float consumedSeconds = coord->Execute(seconds);
    if(IGraphicElement* graphel = GetObject())
    {
        graphel->SetX(coord->GetValue());
    }
    return consumedSeconds;
}
//-----------------------------------------------------------------------------
bool SetXCoord::IsFinished(void) const
{
    return coord->IsFinished();
}
//-----------------------------------------------------------------------------
SetXCoord::~SetXCoord()
{
    delete coord;
}
//-----------------------------------------------------------------------------
SetXCoord* SetXCoord::Copy(void) const
{
    return new SetXCoord(*coord);;
}
//-----------------------------------------------------------------------------
void SetXCoord::Accept(Core::Inspector& inspector)
{
    inspector.Inspect(*this);
}
//-----------------------------------------------------------------------------
SetYCoord::SetYCoord(float coord)
: Command<IGraphicElement>(0l)
, coord(new Value(coord))
{}
//-----------------------------------------------------------------------------
SetYCoord::SetYCoord(const Value& coord)
: Command<IGraphicElement>(0l)
, coord(coord.Copy())
{}
//-----------------------------------------------------------------------------
float SetYCoord::Execute(const float seconds)
{
    const float consumedSeconds = coord->Execute(seconds);
    if(IGraphicElement* graphel = GetObject())
    {
        graphel->SetY(coord->GetValue());
    }
    return consumedSeconds;
}
//-----------------------------------------------------------------------------
bool SetYCoord::IsFinished(void) const
{
    return coord->IsFinished();
}
//-----------------------------------------------------------------------------
SetYCoord::~SetYCoord()
{
    delete coord;
}
//-----------------------------------------------------------------------------
SetYCoord* SetYCoord::Copy(void) const
{
    return new SetYCoord(*coord);
}
//-----------------------------------------------------------------------------
void SetYCoord::Accept(Core::Inspector& inspector)
{
    inspector.Inspect(*this);
}
//-----------------------------------------------------------------------------
SetXYCoords::SetXYCoords(float xCoord, float yCoord)
: Command<IGraphicElement>(0l)
, xCoord(new Value(xCoord))
, yCoord(new Value(yCoord))
{}
//-----------------------------------------------------------------------------
SetXYCoords::SetXYCoords(const Value& xCoord, const Value& yCoord)
: Command<IGraphicElement>(0l)
, xCoord(xCoord.Copy())
, yCoord(yCoord.Copy())
{}
//-----------------------------------------------------------------------------
SetXYCoords::SetXYCoords(const Value& xCoord, const float yCoord)
: Command<IGraphicElement>(0l)
, xCoord(xCoord.Copy())
, yCoord(new Value(yCoord))
{}
//-----------------------------------------------------------------------------
SetXYCoords::SetXYCoords(const float xCoord, const Value& yCoord)
: Command<IGraphicElement>(0l)
, xCoord(new Value(xCoord))
, yCoord(yCoord.Copy())
{}
//-----------------------------------------------------------------------------
float SetXYCoords::Execute(const float seconds)
{
    const float xConsumedSeconds = xCoord->Execute(seconds);
    const float yConsumedSeconds = yCoord->Execute(seconds);
    if(IGraphicElement* graphel = GetObject())
    {
        graphel->SetXY(xCoord->GetValue(), yCoord->GetValue());
    }
    return std::max(xConsumedSeconds, yConsumedSeconds);
}
//-----------------------------------------------------------------------------
bool SetXYCoords::IsFinished(void) const
{
    return xCoord->IsFinished() && yCoord->IsFinished();
}
//-----------------------------------------------------------------------------
SetXYCoords::~SetXYCoords()
{
    delete xCoord;
    delete yCoord;
}
//-----------------------------------------------------------------------------
SetXYCoords* SetXYCoords::Copy(void) const
{
    return new SetXYCoords(*xCoord, *yCoord);
}
//-----------------------------------------------------------------------------
void SetXYCoords::Accept(Core::Inspector& inspector)
{
    inspector.Inspect(*this);
}
//-----------------------------------------------------------------------------
SetScale::SetScale(float scale)
: Command<IGraphicElement>(0l)
, scale(new Value(scale))
{}
//-----------------------------------------------------------------------------
SetScale::SetScale(const Value& scale)
: Command<IGraphicElement>(0l)
, scale(scale.Copy())
{}
//-----------------------------------------------------------------------------
float SetScale::Execute(const float seconds)
{
    const float consumedSeconds = scale->Execute(seconds);
    if(IGraphicElement* graphel = GetObject())
    {
        graphel->SetScale(scale->GetValue());
    }
    return consumedSeconds;
}
//-----------------------------------------------------------------------------
bool SetScale::IsFinished(void) const
{
    return scale->IsFinished();
}
//-----------------------------------------------------------------------------
SetScale::~SetScale()
{
    delete scale;
}
//-----------------------------------------------------------------------------
SetScale* SetScale::Copy(void) const
{
    return new SetScale(*scale);
}
//-----------------------------------------------------------------------------
void SetScale::Accept(Core::Inspector& inspector)
{
    inspector.Inspect(*this);
}
//-----------------------------------------------------------------------------
SetXScale::SetXScale(float scale)
: Command<IGraphicElement>(0l)
, scale(new Value(scale))
{}
//-----------------------------------------------------------------------------
SetXScale::SetXScale(const Value& scale)
: Command<IGraphicElement>(0l)
, scale(scale.Copy())
{}
//-----------------------------------------------------------------------------
float SetXScale::Execute(const float seconds)
{
    const float consumedSeconds = scale->Execute(seconds);
    if(IGraphicElement* graphel = GetObject())
    {
        graphel->SetXScale(scale->GetValue());
    }
    return consumedSeconds;
}
//-----------------------------------------------------------------------------
bool SetXScale::IsFinished(void) const
{
    return scale->IsFinished();
}
//-----------------------------------------------------------------------------
SetXScale::~SetXScale()
{
    delete scale;
}
//-----------------------------------------------------------------------------
SetXScale* SetXScale::Copy(void) const
{
    return new SetXScale(*scale);
}
//-----------------------------------------------------------------------------
void SetXScale::Accept(Core::Inspector& inspector)
{
//    inspector.Inspect(*this);
}
//-----------------------------------------------------------------------------
SetYScale::SetYScale(float scale)
: Command<IGraphicElement>(0l)
, scale(new Value(scale))
{}
//-----------------------------------------------------------------------------
SetYScale::SetYScale(const Value& scale)
: Command<IGraphicElement>(0l)
, scale(scale.Copy())
{}
//-----------------------------------------------------------------------------
float SetYScale::Execute(const float seconds)
{
    const float consumedSeconds = scale->Execute(seconds);
    if(IGraphicElement* graphel = GetObject())
    {
        graphel->SetXScale(scale->GetValue());
    }
    return consumedSeconds;
}
//-----------------------------------------------------------------------------
bool SetYScale::IsFinished(void) const
{
    return scale->IsFinished();
}
//-----------------------------------------------------------------------------
SetYScale::~SetYScale()
{
    delete scale;
}
//-----------------------------------------------------------------------------
SetYScale* SetYScale::Copy(void) const
{
    return new SetYScale(*scale);
}
//-----------------------------------------------------------------------------
void SetYScale::Accept(Core::Inspector& inspector)
{
//    inspector.Inspect(*this);
}
//-----------------------------------------------------------------------------
GetGraphicalParam::GetGraphicalParam(IGraphicElement* graphicElement)
: graphicElement(graphicElement)
{
    assert(graphicElement);
}
//-----------------------------------------------------------------------------
GetGraphicalParam::~GetGraphicalParam()
{}
//-----------------------------------------------------------------------------
void GetGraphicalParam::Accept(Core::Inspector& inspector)
{}
//-----------------------------------------------------------------------------
bool GetGraphicalParam::IsFinished(void) const
{
    return true;
}
//-----------------------------------------------------------------------------
GetX::GetX(IGraphicElement* graphicElement)
: GetGraphicalParam(graphicElement)
{}
//-----------------------------------------------------------------------------
GetX::~GetX()
{}
//-----------------------------------------------------------------------------
GetX* GetX::Copy(void) const
{
    return new GetX(graphicElement);
}
//-----------------------------------------------------------------------------
float GetX::Execute(const float)
{
    value = graphicElement->GetX();
    return 0;
}
//-----------------------------------------------------------------------------
GetY::GetY(IGraphicElement* graphicElement)
: GetGraphicalParam(graphicElement)
{}
//-----------------------------------------------------------------------------
GetY::~GetY()
{}
//-----------------------------------------------------------------------------
GetY* GetY::Copy(void) const
{
    return new GetY(graphicElement);
}
//-----------------------------------------------------------------------------
float GetY::Execute(const float)
{
    value = graphicElement->GetY();
    return 0;
}
//-----------------------------------------------------------------------------
GetAlpha::GetAlpha(IGraphicElement* graphicElement)
: GetGraphicalParam(graphicElement)
{}
//-----------------------------------------------------------------------------
GetAlpha::~GetAlpha()
{}
//-----------------------------------------------------------------------------
GetAlpha* GetAlpha::Copy(void) const
{
    return new GetAlpha(graphicElement);
}
//-----------------------------------------------------------------------------
float GetAlpha::Execute(const float)
{
    value = graphicElement->GetAlpha();
    return 0;
}
//-----------------------------------------------------------------------------
GetAngle::GetAngle(IGraphicElement* graphicElement)
: GetGraphicalParam(graphicElement)
{}
//-----------------------------------------------------------------------------
GetAngle::~GetAngle()
{}
//-----------------------------------------------------------------------------
GetAngle* GetAngle::Copy(void) const
{
    return new GetAngle(graphicElement);
}
//-----------------------------------------------------------------------------
float GetAngle::Execute(const float)
{
    value = graphicElement->GetAngle();
    return 0;
}
//-----------------------------------------------------------------------------
GetXAnchor::GetXAnchor(IGraphicElement* graphicElement)
: GetGraphicalParam(graphicElement)
{}
//-----------------------------------------------------------------------------
GetXAnchor::~GetXAnchor()
{}
//-----------------------------------------------------------------------------
GetXAnchor* GetXAnchor::Copy(void) const
{
    return new GetXAnchor(graphicElement);
}
//-----------------------------------------------------------------------------
float GetXAnchor::Execute(const float)
{
    value = graphicElement->GetXAnchor();
    return 0;
}
//-----------------------------------------------------------------------------
GetYAnchor::GetYAnchor(IGraphicElement* graphicElement)
: GetGraphicalParam(graphicElement)
{}
//-----------------------------------------------------------------------------
GetYAnchor::~GetYAnchor()
{}
//-----------------------------------------------------------------------------
GetYAnchor* GetYAnchor::Copy(void) const
{
    return new GetYAnchor(graphicElement);
}
//-----------------------------------------------------------------------------
float GetYAnchor::Execute(const float)
{
    value = graphicElement->GetYAnchor();
    return 0;
}
//-----------------------------------------------------------------------------
GetXScale::GetXScale(IGraphicElement* graphicElement)
: GetGraphicalParam(graphicElement)
{}
//-----------------------------------------------------------------------------
GetXScale::~GetXScale()
{}
//-----------------------------------------------------------------------------
GetXScale* GetXScale::Copy(void) const
{
    return new GetXScale(graphicElement);
}
//-----------------------------------------------------------------------------
float GetXScale::Execute(const float)
{
    value = graphicElement->GetXScale();
    return 0;
}
//-----------------------------------------------------------------------------
GetYScale::GetYScale(IGraphicElement* graphicElement)
: GetGraphicalParam(graphicElement)
{}
//-----------------------------------------------------------------------------
GetYScale::~GetYScale()
{}
//-----------------------------------------------------------------------------
GetYScale* GetYScale::Copy(void) const
{
    return new GetYScale(graphicElement);
}
//-----------------------------------------------------------------------------
float GetYScale::Execute(const float)
{
    value = graphicElement->GetYScale();
    return 0;
}
